package com.google.wavesurferrobot.textmining;

/*
*************************************************************************************************
* File:         ChiSquare.java                                                                  *
* Usage:        ChiSquare implements the X^2 measure                                            *
*************************************************************************************************
* IDE/Compiler: For the development needs we used NetBeans 5.0 and JRE 1.5.0_06 on WinXP Home   *
*************************************************************************************************
* License:      (LGPL) GNU Lesser General Public License                                        *
*               http://www.opensource.org/licenses/lgpl-license.php                             *
*************************************************************************************************
*         Originally written by George Tsatsaros (gbt@aueb.gr)                                  *      
*               Author         :  Panayiotis Papadopoulos (3010010)                             *
*               Website        :  http://dias.aueb.gr/~p3010010/                                *
*               E-mail         :  papado@freemail.gr                                            *
*                                 p3010010@dias.aueb.gr                                         *
*               MSN messenger  :  pap5@hotmail.com                                              *
*               Skype          :  papOnSlayer                                                   *
*                                                                                               *
* Contact:  Feel free to contact with me for any question/suggestion using the email(s) above   *
*************************************************************************************************
*/

import java.util.Enumeration;
import java.util.Hashtable;
import java.lang.Math.*;

public class ChiSquare
{
    private String token;

    private double chiSq;


    public ChiSquare(String token, int documentsNum, Hashtable category)
    {
        this.token = token;
        computeChiSquare(documentsNum, category);
    }

    public double getChiSquare()
    {
        return chiSq;
    }

    //CHI(t) = Sum(Pr(Ci) * CHI(t,Ci))
    private void computeChiSquare(int documentsNum, Hashtable category)
    {
        chiSq = 0;

        for (Enumeration e = category.elements(); e.hasMoreElements(); )
        {
            Category catObj = (Category) e.nextElement();
            double probC = catObj.getCategoryProbability();

            ChiSqStat chiSqObj = new ChiSqStat(token, catObj, category, documentsNum);
            chiSq += probC * chiSqObj.getChiSqStat();
        }
    }


//-------------- inner class

    class ChiSqStat
    {
        private String token;

        private int A;    //Number of documents in c containing t
        private int B;    //Number of documents not in c, containing t
        private int C;    //Number of documents in c not containing t
        private int D;    //Number of documents not in c, not containing t
        private int N;    //Number of documents

        private double chiSqStat;


        public ChiSqStat(String token, Category thisCatObj, Hashtable category, int documentsNum)
        {
            this.token = token;
            this.N = documentsNum;
            computeChiSqStat(thisCatObj, category);
        }

        public double getChiSqStat()
        {
            return chiSqStat;
        }

        //CHI(t,Ci) = (N * (A*D-C*B)^2) / ((A+C)*(B+D)*(A+B)*(C+D))
        private void computeChiSqStat(Category thisCatObj, Hashtable category)
        {
            computeA_C_B_D(thisCatObj, category);

            chiSqStat = ((double) (N * Math.pow(((A * D) - (C * B)), 2))) / ((double) ((A + C) * (B + D) * (A + B) * (C + D)));
        }

        //A = Number of documents in thisCatObj, containing token
        //C = Number of documents in thisCatObj, not containing token
        //B = Number of documents not in thisCatObj, containing token
        //D = Number of documents not in thisCatObj, not containing token
        private void computeA_C_B_D(Category thisCatObj, Hashtable category)
        {
            A = 0;
            C = 0;
            B = 0;
            D = 0;

            for (Enumeration e = category.elements(); e.hasMoreElements(); )
            {
                Category catObj = (Category) e.nextElement();
                String catName = catObj.getCategoryName();

                if (catName.equals(thisCatObj.getCategoryName()))
                {
                    for (Enumeration en = catObj.getCategoryDocuments().elements(); en.hasMoreElements(); )
                    {
                        Document docObj = (Document) en.nextElement();

                        if (docObj.tokenExists(token))
                            A += 1;
                        else
                            C += 1;
                    }
                }
                else
                {
                    for (Enumeration en = catObj.getCategoryDocuments().elements(); en.hasMoreElements(); )
                    {
                        Document docObj = (Document) en.nextElement();

                        if (docObj.tokenExists(token))
                            B += 1;
                        else
                            D += 1;
                    }
                }
            }
        }

    }//Inner Class CHISqStat.

}//Class ChiSquare.
